 /*
 * game.c
 *
 *  Created on: Jun 4, 2011
 *      Author: mariesophie
 */

#include <assert.h>
#include "prisoner.h"

sfSprite *Joueur;
int jX, jY;
int tX, tY;

//
// entité porte
//
// targetname = "porte"

//
// entité bouton
//
// target = "porte"
// targetname = "bouton"
//
// [bouton] ------> [porte]
//

typedef struct
{
	int used; // la variable est-elle utilisée ?
	int currentX, currentY; // actuel
	int targetX, targetY; // destination
	int moving;
	sfSprite *spriteCaisse;
} caisse_t;

// entite_t;
// entite_t entities(64);

caisse_t caisse[MAX_CAISSES];

typedef struct
{
	int used; // la variable est-elle utilisée ?
	int currentX, currentY; // actuel
	int targetX, targetY; // destination
	int moving;
	sfSprite *spriteGarde;
} garde_t;

garde_t garde[MAX_GARDE];

sfClock *mvClock;
char moving;
int Cle = 0;
int Porte = 0;


/*
 * gm_Init
 *
 * Fonction d'initialisation du jeu
 *
 */
int gm_Init() {
	int x, y;

	jY = 0;
	jX = 0;
	Joueur = 0;
	moving = 0;
	mvClock = sfClock_Create();

	imgJoueur_droite[1] = sfImage_CreateFromFile("joueur_droite_1.png");
	imgJoueur_gauche[1] = sfImage_CreateFromFile("joueur_gauche_1.png");
	imgJoueur_haut[1] = sfImage_CreateFromFile("joueur_haut_1.png");
	imgJoueur_bas[1] = sfImage_CreateFromFile("joueur_bas_1.png");
	imgJoueur_droite[0] = sfImage_CreateFromFile("joueur_droite_0.png");
	imgJoueur_gauche[0] = sfImage_CreateFromFile("joueur_gauche_0.png");
	imgJoueur_haut[0] = sfImage_CreateFromFile("joueur_haut_0.png");
	imgJoueur_bas[0] = sfImage_CreateFromFile("joueur_bas_0.png");
	imgJoueur_droite[2] = sfImage_CreateFromFile("joueur_droite_2.png");
	imgJoueur_gauche[2] = sfImage_CreateFromFile("joueur_gauche_2.png");
	imgJoueur_haut[2] = sfImage_CreateFromFile("joueur_haut_2.png");
	imgJoueur_bas[2] = sfImage_CreateFromFile("joueur_bas_2.png");


	// Initialisation du tableau des décorations et entités
	for (x = 0; x < NOMBRE_CASES_LONGUEUR; x++)
	{
		for (y = 0; y < NOMBRE_CASES_LARGEUR; y++)
		{
			grille[x][y] = NULL;
			entites[x][y] = NULL;
		}
	}

	// On met toutes les caisses à zéro
	for (x = 0; x < MAX_CAISSES; x++)
	{
		caisse[x].used = 0;
		caisse[x].spriteCaisse = 0;
		caisse[x].targetX = 0;
		caisse[x].targetY = 0;
		caisse[x].currentX = 0;
		caisse[x].currentY = 0;
	}
	for (x = 0; x < MAX_CAISSES; x++)
	{
		garde[x].used = 0;
		garde[x].spriteGarde = 0;
		garde[x].targetX = 0;
		garde[x].targetY = 0;
		garde[x].currentX = 0;
		garde[x].currentY = 0;
	}

	 //chargement du fichier de niveau
	gm_Load("niveau1.txt");

	return 1;
}


/*
 * gm_Load()
 *
 * Chargement du fichier de niveau dans l'éditeur
 */
int gm_Load(const char* niveau)
{
	char Case;
	int i, x, y, nombre;
	char direction;

	// ouverture du fichier niveau en mode lecture binaire
	FILE* f = fopen(niveau, "rb");

	// si il est impossible de l'ouvrir, on quitte la fonction
	if (f == NULL)
		return 0;


	// le premier entier est le nombre de cases décoration enregistrées
	fread(&nombre, sizeof(int), 1, f);

	// pour chaque case décoration
	for (i = 0; i < nombre; i++)
	{
		// extraction des informations de la case
		fread(&Case, sizeof(char), 1, f);
		fread(&x, sizeof(int), 1, f);
		fread(&y, sizeof(int), 1, f);

		// création de la case de décoration
		grille[x][y] = sfSprite_Create();

		if (Case == CASE_SOL)
			sfSprite_SetImage(grille[x][y], imgSol);
		else if (Case == CASE_MUR)
			sfSprite_SetImage(grille[x][y], imgMur);

		sfSprite_SetPosition(grille[x][y], x * LONGUEUR_CASE, y * LARGEUR_CASE);
	}

	fread(&nombre, sizeof(int), 1, f);

	for (i = 0; i < nombre; i++)
	{
		// extraction des informations de la case
		fread(&Case, sizeof(char), 1, f);
		fread(&direction, sizeof(char), 1, f);
		fread(&x, sizeof(int), 1, f);
		fread(&y, sizeof(int), 1, f);

		// création de la case d'entite
		entites[x][y] = sfSprite_Create();

		if (Case == ENTITE_DEPART)
		{
			Joueur = sfSprite_Create();

			if (direction == DIR_DROITE)
				sfSprite_SetImage(Joueur, imgJoueur_droite[0]);
			else if (direction == DIR_GAUCHE)
				sfSprite_SetImage(Joueur, imgJoueur_gauche[0]);
			else if (direction == DIR_HAUT)
				sfSprite_SetImage(Joueur, imgJoueur_haut[0]);
			else if (direction == DIR_BAS)
				sfSprite_SetImage(Joueur, imgJoueur_bas[0]);

			jX = x;
			jY = y;

			tX = x;
			tY = y;

			sfSprite_SetPosition(Joueur, jX * LONGUEUR_CASE, jY * LARGEUR_CASE);
		}
		else if (Case == ENTITE_ARRIVE)
			sfSprite_SetImage(entites[x][y], imgArrivee);
		else if (Case == ENTITE_CLE)
			sfSprite_SetImage(entites[x][y], imgCle);
		else if (Case == ENTITE_CAISSE)
		{
			int c;
			//sfSprite_SetImage(entites[x][y], imgCaisse);

			sfSprite_Destroy(entites[x][y]);
			entites[x][y] = 0;
			// On cherche une caisse disponible
			for (c = 0; c < MAX_CAISSES; c++)
			{
				// Une caisse de libre, utilisons-la.
				if (caisse[c].used == 0)
				{
					caisse[c].used = 1;

					caisse[c].currentX = x;
					caisse[c].currentY = y;
					caisse[c].moving = 0;

					caisse[c].spriteCaisse = sfSprite_Create();
					sfSprite_SetPosition(caisse[c].spriteCaisse, x * LONGUEUR_CASE, y * LONGUEUR_CASE);
					sfSprite_SetImage(caisse[c].spriteCaisse, imgCaisse);

					break; // A ne surtout pas oublier
				}
			}
			for (c = 0; c < MAX_GARDE; c++)
			{
				 //Une caisse de libre, utilisons-la.
				if (garde[c].used == 0)
				{
					//garde[c].used = 1;

					garde[c].currentX = x;
					garde[c].currentY = y;
					garde[c].moving = 0;

					garde[c].spriteGarde = sfSprite_Create();
					sfSprite_SetPosition(garde[c].spriteGarde, x * LONGUEUR_CASE, y * LONGUEUR_CASE);
					sfSprite_SetImage(garde[c].spriteGarde, imgGarde_droite[1]);

					break; // A ne surtout pas oublier
				}
			}
		}
		else if (Case == ENTITE_PORTE_FERMEE)
			sfSprite_SetImage(entites[x][y], imgPorte_fermee);

		if (entites[x][y])
			sfSprite_SetPosition(entites[x][y], x * LONGUEUR_CASE, y * LARGEUR_CASE);
	}

	// fermeture du fichier
	fclose(f);
	return 1;
}


/*
 * gm_ProcessEvent
 *
 * Traitement des événements
 *
 * -- Void gm_Player (Conditions pour que le joueur puisse se déplacer)
 * -- Void gm_Déplacement (Gere les déplacements du joueur ainsi que les objects clé et arrivée)
 * -- Void gm_Moving2 (Permet l'enchénement des images du joueur ainsi que l'ouverture de la porte)
 * -- void gm_Moving (déplacement du joueur sur la case destination et fermeture des portes)
 *
 */
int gm_ProcessEvent(sfEvent evt)
{
	if (evt.Type == sfEvtKeyPressed)
	{
		if (evt.Key.Code == sfKeyEscape)
			sfRenderWindow_Close(App);
	}
	return 1;
}

//Conditions pour que le joueur puisse se déplacer
void gm_Player(int x, int y, int X, int Y)
{
	int c;

	if (!grille[x][y])
		return;

	if(sfSprite_GetImage(grille[x][y]) != imgSol)
	{
		if ((entites[x][y] &&  sfSprite_GetImage(entites[x][y]) == imgPorte_fermee) && (Cle != 1 ))
			return;
	}

	if(entites[x][y] && entites[X][Y])
		return;

	// Y-a-t'il une caisse à coté ?
	for (c = 0; c < MAX_CAISSES; c++)
	{
		if (caisse[c].used == 1 && //caisse[c].moving == 0 &&
				caisse[c].currentX == x && caisse[c].currentY == y)
		{
			int cn;

			// Y-a-t'il un obstacle à coté ?
			if (!grille[X][Y] || (grille[X][Y] && sfSprite_GetImage(grille[X][Y]) != imgSol))
				return;

			for (cn = 0; cn < MAX_CAISSES; cn++)
			{
				if (c != cn)
				{
					if (caisse[cn].currentX == X && caisse[cn].currentY == Y)
						return;
				}
			}

			caisse[c].moving = 1;
			caisse[c].targetX = X;
			caisse[c].targetY = Y;
			break;
		}
	}

	moving = 1;
	tX = x;
	tY = y;
}

//Gere les déplacements du joueur ainsi que les objets (clé et arrivée)
void gm_Deplacement()
{
	sfInput* Input = sfRenderWindow_GetInput(App);

	int x,y;

	if(moving)
		return;

	//gestion des touches directionnelles
	if (sfInput_IsKeyDown(Input, sfKeyRight) && (jX < NOMBRE_CASES_LONGUEUR - 1))
	{
		gm_Player(jX + 1, jY, jX +2, jY);
	}
	else if (sfInput_IsKeyDown(Input, sfKeyLeft) && (jX > 0))
	{
		gm_Player(jX - 1, jY, jX -2, jY);
	}
	else if (sfInput_IsKeyDown(Input, sfKeyUp) && (jY > 0))
	{
		gm_Player(jX, jY - 1, jX, jY -2);
	}
	else if (sfInput_IsKeyDown(Input, sfKeyDown) && (jY < NOMBRE_CASES_LARGEUR - 1))
	{
		gm_Player(jX, jY + 1, jX, jY +2);
	}

	//Gestion de la case Cle
	if(entites[jX][jY] && sfSprite_GetImage(entites[jX][jY]) == imgCle)
	{
		sfSprite_Destroy(entites[jX][jY]);
		entites[jX][jY] = NULL;
		Cle = 1;
	}

	//Gestion de la case Arrivée
	if(entites[jX][jY] && sfSprite_GetImage(entites[jX][jY]) == imgArrivee)
	{
		for (x = 0; x< NOMBRE_CASES_LONGUEUR; x++)
		{
			for (y = 0; y< NOMBRE_CASES_LARGEUR; y++)
			{
				grille[x][y] = NULL;
				entites[x][y] = NULL;
			}
		}
		moving = 0;

		for (x = 0; x < MAX_CAISSES; x++)
		{
			caisse[x].used = 0;
			sfSprite_Destroy(caisse[x].spriteCaisse);
			caisse[x].spriteCaisse = 0;
			caisse[x].targetX = 0;
			caisse[x].targetY = 0;
			caisse[x].currentX = 0;
			caisse[x].currentY = 0;
		}

		gm_Load("niveau2.txt");
	}



}

//Permet l'enchénement des images du joueur ainsi que l'ouverture de la porte
void gm_Moving2(sfSprite* sprite1, sfSprite* sprite2, float x, float y, int X, int Y)
{
	if((sfClock_GetTime(mvClock) * 1000) > 200.0f)
	{
		if(sfSprite_GetImage(Joueur) == sprite1)
		{
			sfSprite_SetImage(Joueur, sprite2);
			sfClock_Reset(mvClock);
		}
		else
		{
			sfSprite_SetImage(Joueur, sprite1);
			sfClock_Reset(mvClock);
		}
	}

	if(entites[X][Y] && sfSprite_GetImage(entites[X][Y]) == imgPorte_fermee)
	{
		sfSprite_SetImage(entites[X][Y], imgPorte_ouverte);
	}

	sfSprite_Move(Joueur, x, y);
}

void gm_MovingCaisses()
{
	int c;

	for (c = 0; c < MAX_CAISSES; c++)
	{
		if (caisse[c].used == 1 && caisse[c].moving == 1)
		{
			float origineX, origineY;
			float destinationX, destinationY;

			origineX = caisse[c].currentX * LONGUEUR_CASE;
			origineY = caisse[c].currentY * LARGEUR_CASE;

			destinationX = caisse[c].targetX * LONGUEUR_CASE;
			destinationY = caisse[c].targetY * LARGEUR_CASE;

			if (origineX < destinationX)
			{
				sfSprite_Move(caisse[c].spriteCaisse, 1.0f, 0.0f);

				if (sfSprite_GetX(caisse[c].spriteCaisse) >= destinationX)
				{
					caisse[c].currentX = caisse[c].targetX;
					caisse[c].currentY = caisse[c].targetY;
					sfSprite_SetPosition(caisse[c].spriteCaisse, destinationX, destinationY);
					caisse[c].moving = 0;
				}
			}

			//déplacement du joueur sur la case destination (gauche) et fermeture de la porte
			if(origineX > destinationX)
			{
				sfSprite_Move(caisse[c].spriteCaisse, -1.0f, 0.0f);

				if (sfSprite_GetX(caisse[c].spriteCaisse) <= destinationX)
				{
					caisse[c].currentX = caisse[c].targetX;
					caisse[c].currentY = caisse[c].targetY;
					sfSprite_SetPosition(caisse[c].spriteCaisse, destinationX, destinationY);
					caisse[c].moving = 0;
				}
			}

			//déplacement du joueur sur la case destination (bas) et fermeture de la porte
			if(origineY < destinationY)
			{
				sfSprite_Move(caisse[c].spriteCaisse, 0.0f, 1.0f);

				if (sfSprite_GetY(caisse[c].spriteCaisse) >= destinationY)
				{
					caisse[c].currentX = caisse[c].targetX;
					caisse[c].currentY = caisse[c].targetY;
					sfSprite_SetPosition(caisse[c].spriteCaisse, destinationX, destinationY);
					caisse[c].moving = 0;
				}
			}

			//déplacement du joueur sur la case destination (haut) et fermeture de la porte
			if(origineY > destinationY)
			{
				sfSprite_Move(caisse[c].spriteCaisse, 0.0f, -1.0f);

				if (sfSprite_GetY(caisse[c].spriteCaisse) <= destinationY)
				{
					caisse[c].currentX = caisse[c].targetX;
					caisse[c].currentY = caisse[c].targetY;
					sfSprite_SetPosition(caisse[c].spriteCaisse, destinationX, destinationY);
					caisse[c].moving = 0;
				}
			}
		}
	}
}

//déplacement du joueur sur la case destination et fermeture des portes
void gm_Moving()
{

	if(!moving)
		return;

		float origineX, origineY;
		float destinationX, destinationY;

		origineX = jX * LONGUEUR_CASE;
		origineY = jY * LARGEUR_CASE;

		destinationX = tX * LONGUEUR_CASE;
		destinationY = tY * LARGEUR_CASE;

		//déplacement du joueur sur la case destination (droite) et fermeture de la porte
		if (origineX < destinationX)
		{
			gm_Moving2(imgJoueur_droite[1], imgJoueur_droite[2], 1.0f, 0.0f, jX +1, jY);

			if (sfSprite_GetX(Joueur) >= destinationX)
			{
				jX = tX;
				jY = tY;
				sfSprite_SetPosition(Joueur, destinationX, destinationY);

				if(entites[jX -1][jY] && sfSprite_GetImage(entites[jX -1][jY]) == imgPorte_ouverte)
				{
					sfSprite_SetImage(entites[jX -1][jY], imgPorte_fermee);
				}
				if(entites[jX -1][jY] && sfSprite_GetImage(entites[jX -1][jY]) == imgCaisse)
				{

				}
				moving = 0;
			}
		}

		//déplacement du joueur sur la case destination (gauche) et fermeture de la porte
		if(origineX > destinationX)
		{
			gm_Moving2(imgJoueur_gauche[1], imgJoueur_gauche[2], -1.0f, 0.0f, jX-1, jY);

			if (sfSprite_GetX(Joueur) <= destinationX)
			{
				jX = tX;
				jY = tY;
				sfSprite_SetPosition(Joueur, destinationX, destinationY);
				if(entites[jX +1][jY] && sfSprite_GetImage(entites[jX +1][jY]) == imgPorte_ouverte)
				{
					sfSprite_SetImage(entites[jX +1][jY], imgPorte_fermee);
				}
				moving = 0;
			}
		}

		//déplacement du joueur sur la case destination (bas) et fermeture de la porte
		if(origineY < destinationY)
		{
			gm_Moving2(imgJoueur_bas[1], imgJoueur_bas[2], 0.0f, 1.0f, jX, jY+1);

			if (sfSprite_GetY(Joueur) >= destinationY)
			{
				jX = tX;
				jY = tY;
				sfSprite_SetPosition(Joueur, destinationX, destinationY);
				if(entites[jX][jY -1] && sfSprite_GetImage(entites[jX][jY -1]) == imgPorte_ouverte)
				{
					sfSprite_SetImage(entites[jX][jY -1], imgPorte_fermee);
				}
				moving = 0;
			}
		}

		//déplacement du joueur sur la case destination (haut) et fermeture de la porte
		if(origineY > destinationY)
		{
			gm_Moving2(imgJoueur_haut[1], imgJoueur_haut[2], 0.0f, -1.0f, jX, jY-1);

			if(sfSprite_GetY(Joueur) <= destinationY)
			{
				jX = tX;
				jY = tY;
				sfSprite_SetPosition(Joueur, destinationX, destinationY);
				if(entites[jX][jY +1] && sfSprite_GetImage(entites[jX][jY +1]) == imgPorte_ouverte)
				{
					sfSprite_SetImage(entites[jX][jY +1], imgPorte_fermee);
				}
				moving = 0;
			}
		}
}
//déplacement du garde
void gm_garde()
{

}


/*
 * gm_Loop
 * Fonction de la boucle de l'éditeur
 *
 * - Appel à la fonction de traitement des événements
 * - Appel à la fonction d'affichage (dessin des cases,...)
 *
 */
int gm_Loop()
{
	int x, y;

	// affichage des cases de décoration et d'entité
	for (x = 0; x < NOMBRE_CASES_LONGUEUR; x++)
	{
		for (y = 0; y < NOMBRE_CASES_LARGEUR; y++)
		{
			if (grille[x][y] != NULL)
				sfRenderWindow_DrawSprite(App, grille[x][y]);
			if (entites[x][y] != NULL)
				sfRenderWindow_DrawSprite(App, entites[x][y]);
		}
	}

	// affichage des caisses
	for (x = 0; x < MAX_CAISSES; x++)
	{
		if (caisse[x].used == 1)
			sfRenderWindow_DrawSprite(App, caisse[x].spriteCaisse);
	}

	gm_Deplacement();
	gm_Moving();
	gm_MovingCaisses();

	//sfSprite_SetPosition(Joueur, jX * LONGUEUR_CASE, jY * LARGEUR_CASE);
	sfRenderWindow_DrawSprite(App, Joueur);

	return 0;
}

/*
 * gm_Destroy
 *
 * Destruction de l'éditeur
 */
int gm_Destroy()
{
	return 0;
}

